// Copyright (C)2012 Johann Duscher. All rights reserved.
//
// This file is part of QwTAPI.
//
// QwTAPI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// QwTAPI is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with QwTAPI.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include "stdafx.h"
#include "Request.h"

#define CONNECTION_DEFAULT_REQUEST_TIMEOUT (10 * 1000)


namespace qwtapi
{

class Line;

class QWTAPI_EXPORT Connection : public QObject
{
    Q_OBJECT

    friend class Line;
    friend class Call;
    friend class Request;

public:
    typedef QList<Line*> LineList;
    typedef QMap<LONG, Request*> RequestMap;

    static Connection* instance();

    Connection(QObject *parent = 0);
    ~Connection();

    LONG initialize(const QString& appName, DWORD apiVersion);
    LONG shutdown();

    LONG openLine(Line** ppLine, CallPrivilege::Constants callPrivileges, MediaMode::Constants mediaModes, DWORD apiVersion, DWORD extVersion, LPLINECALLPARAMS const pCallParams);

    HLINEAPP getLineAppHandle() const;
    Line* getLineFromDeviceId(DWORD deviceId) const;
    DWORD getLineDeviceCount() const;
    LineList findLines(MediaMode::Constants mediaModes) const;
    Request* findRequestForId(LONG requestId) const;

protected slots:
    void onTAPIEvent(DWORD hDevice, qwtapi::Message::Constant msg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);

protected:
    LONG initLines(const QString& appName, DWORD apiVersion);

    void onLineClose(DWORD deviceId);
    void onLineCreate(DWORD deviceId);
    void onLineRemove(DWORD deviceId);
    void onLineReply(LONG requestId, LONG result);

    Request* createRequest(QObject* pSignalReceiver, const char* pMethod);
    void addRequest(Request* pRequest, Request::Type requestType, LONG requestId, int timeout = CONNECTION_DEFAULT_REQUEST_TIMEOUT);
    bool removeRequest(LONG requestId); // Called by Request's destructor.

private:
    HLINEAPP m_hLineApp;

    mutable QMutex m_lineListMutex;
    LineList m_lineList;

    mutable QMutex m_requestMapMutex;
    RequestMap m_requestMap;

    static void CALLBACK tapiCallback(DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
};

}
